/**
 * Copyright 2012 Brigham Young University
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package edu.byu.nlp.al;

/**
 * @author rah67
 *
 */
public class AnnotationClient<L, D> {
	
	public static interface DataModel<L, D> {
		void setInstance(D instance);
		L getAnnotation();
	}
	
	private static class Request<L> implements StoreAnnotationRequest<L> {
		
		private final long annotatorId;
		private L annotation;
		private long requestId;
		
		private long requestIssuedTime;
		private long instanceReceivedTime;
		private long annotationStartTime;
		private long annotationEndTime;
		private long responseSentTime;
		
		public Request(long annotatorId) {
			this.annotatorId = annotatorId;
		}

		@Override
		public long getRequestIssuedTime() {
			return requestIssuedTime;
		}
		
		public void requestIssued() {
			this.requestIssuedTime = System.nanoTime();
		}

		@Override
		public long getInstanceReceivedTime() {
			return instanceReceivedTime;
		}

		public void instanceReceived() {
			this.instanceReceivedTime = System.nanoTime();
		}

		@Override
		public long getAnnotationStartTime() {
			return annotationStartTime;
		}

		public void startAnnotation() {
			this.annotationStartTime = System.nanoTime();
		}

		@Override
		public long getAnnotationEndTime() {
			return annotationEndTime;
		}

		public void endAnnotation() {
			this.annotationEndTime = System.nanoTime();
		}

		@Override
		public long getResponseSentTime() {
			return responseSentTime;
		}

		public void responseSent() {
			this.responseSentTime = System.nanoTime();
		}

		@Override
		public long getAnnotatorId() {
			return annotatorId;
		}

		@Override
		public long getRequestId() {
			return requestId;
		}

		public void setRequestId(long requestId) {
			this.requestId = requestId;
		}
		
		@Override
		public L getAnnotation() {
			return annotation;
		}
		
		public void setAnnotation(L annotation) {
			this.annotation = annotation;
		}
		
	}
	
	private final AnnotationServer<L, D> annotationServer;
	private final DataModel<L, D> dataModel;
	private final long annotatorId;
	private Request<L> request;
	
	public void onInitialize() {
		request = new Request<L>(annotatorId);
		requestInstance();
	}
	
	public void onSubmitAndNext() {
		sendResponse();
		request = new Request<L>(annotatorId);
		requestInstance();
	}
	
	public void onCancel() {
		annotationServer.cancelInstanceRequest(request.getRequestId());
	}
	
	public void onSubmitAndFinish() {
		sendResponse();
	}
	
	private void requestInstance() {
		request.requestIssued();
		// RPC
		InstanceForAnnotation<D> response = annotationServer.requestInstance(annotatorId);
		request.instanceReceived();
		request.setRequestId(response.getRequestId());
		dataModel.setInstance(response.getInstance());
		request.startAnnotation();
	}
	
	private void sendResponse() {
		request.endAnnotation();
		request.setAnnotation(dataModel.getAnnotation());
		request.responseSent();
		// RPC
		StoreAnnotationResponse response = annotationServer.requestStoreAnnotation(request);
	}
}
